"""
Edge-TTS implementation for Microsoft Edge Text-to-Speech.

Free TTS service with high-quality neural voices.
"""

import asyncio
import json
from pathlib import Path
from typing import Dict, List, Optional, Any
import tempfile
import hashlib

from .base_tts import BaseTTSEngine, TTSConfig, TTSRequest, VoiceInfo, TTSError, TTSEngineError


class EdgeTTSEngine(BaseTTSEngine):
    """Edge-TTS implementation using Microsoft Edge Text-to-Speech."""
    
    def __init__(self, config: Optional[TTSConfig] = None):
        """Initialize Edge-TTS engine."""
        super().__init__(config)
        self._edge_tts = None
        self._communicate = None
        
        # Predefined voice list (most common ones)
        self._builtin_voices = [
            VoiceInfo("zh-CN-XiaoxiaoNeural", "晓晓 (女声)", "zh-CN", "Female", "zh-CN", 24000, "活泼、温暖的女声"),
            VoiceInfo("zh-CN-YunxiNeural", "云希 (男声)", "zh-CN", "Male", "zh-CN", 24000, "稳重、磁性的男声"),
            VoiceInfo("zh-CN-YunyangNeural", "云扬 (男声)", "zh-CN", "Male", "zh-CN", 24000, "开朗、阳光的男声"),
            VoiceInfo("zh-CN-XiaoyiNeural", "晓怡 (女声)", "zh-CN", "Female", "zh-CN", 24000, "甜美、亲和的女声"),
            VoiceInfo("zh-CN-YunjianNeural", "云健 (男声)", "zh-CN", "Male", "zh-CN", 24000, "运动、活力的男声"),
            VoiceInfo("zh-CN-XiaochenNeural", "晓辰 (女声)", "zh-CN", "Female", "zh-CN", 24000, "温和、舒缓的女声"),
            VoiceInfo("zh-CN-XiaohanNeural", "晓涵 (女声)", "zh-CN", "Female", "zh-CN", 24000, "严肃、冷静的女声"),
            VoiceInfo("zh-CN-XiaomoNeural", "晓墨 (女声)", "zh-CN", "Female", "zh-CN", 24000, "温柔、知性的女声"),
            VoiceInfo("zh-CN-XiaoqiuNeural", "晓秋 (女声)", "zh-CN", "Female", "zh-CN", 24000, "成熟、优雅的女声"),
            VoiceInfo("zh-CN-XiaoruiNeural", "晓睿 (女声)", "zh-CN", "Female", "zh-CN", 24000, "理智、专业的女声"),
            VoiceInfo("zh-CN-XiaoshuangNeural", "晓双 (女声)", "zh-CN", "Female", "zh-CN", 24000, "少女、清纯的女声"),
            VoiceInfo("zh-CN-XiaoxuanNeural", "晓萱 (女声)", "zh-CN", "Female", "zh-CN", 24000, "播音、正式的女声"),
            VoiceInfo("zh-CN-XiaoyanNeural", "晓颜 (女声)", "zh-CN", "Female", "zh-CN", 24000, "客服、友好的女声"),
            VoiceInfo("zh-CN-XiaoyouNeural", "晓悠 (女声)", "zh-CN", "Female", "zh-CN", 24000, "童声、可爱的女声"),
            VoiceInfo("zh-CN-XiaozhenNeural", "晓甄 (女声)", "zh-CN", "Female", "zh-CN", 24000, "文艺、温柔的女声"),
            VoiceInfo("zh-CN-YunfengNeural", "云枫 (男声)", "zh-CN", "Male", "zh-CN", 24000, "成熟、严肃的男声"),
            VoiceInfo("zh-CN-YunhaoNeural", "云浩 (男声)", "zh-CN", "Male", "zh-CN", 24000, "广告、大气的男声"),
            VoiceInfo("zh-CN-YunyeNeural", "云野 (男声)", "zh-CN", "Male", "zh-CN", 24000, "专业、播音的男声"),
            VoiceInfo("zh-CN-YunzeNeural", "云泽 (男声)", "zh-CN", "Male", "zh-CN", 24000, "老年、稳重的男声"),
            # English voices
            VoiceInfo("en-US-AriaNeural", "Aria (Female)", "en-US", "Female", "en-US", 24000, "Natural, conversational female voice"),
            VoiceInfo("en-US-DavisNeural", "Davis (Male)", "en-US", "Male", "en-US", 24000, "Natural, conversational male voice"),
            VoiceInfo("en-US-GuyNeural", "Guy (Male)", "en-US", "Male", "en-US", 24000, "Professional male voice"),
            VoiceInfo("en-US-JaneNeural", "Jane (Female)", "en-US", "Female", "en-US", 24000, "Professional female voice"),
            VoiceInfo("en-US-JasonNeural", "Jason (Male)", "en-US", "Male", "en-US", 24000, "Casual male voice"),
            VoiceInfo("en-US-JennyNeural", "Jenny (Female)", "en-US", "Female", "en-US", 24000, "Friendly female voice"),
            VoiceInfo("en-US-NancyNeural", "Nancy (Female)", "en-US", "Female", "en-US", 24000, "Mature female voice"),
            VoiceInfo("en-US-TonyNeural", "Tony (Male)", "en-US", "Male", "en-US", 24000, "Mature male voice"),
        ]
    
    async def _ensure_edge_tts(self):
        """Ensure edge-tts is imported and available."""
        if self._edge_tts is None:
            try:
                import edge_tts
                self._edge_tts = edge_tts
                self._communicate = edge_tts.Communicate
            except ImportError:
                raise TTSEngineError(
                    "edge-tts not installed. Install with: pip install edge-tts"
                )
    
    async def synthesize(self, request: TTSRequest) -> str:
        """Synthesize speech using Edge-TTS."""
        await self._ensure_edge_tts()
        
        try:
            # Validate configuration
            self.validate_config(request.config)
            
            # Create SSML text with voice settings
            ssml_text = self._create_ssml(request.text, request.config)
            
            # Create communication object
            communicate = self._communicate(ssml_text, request.config.voice_id)
            
            # Ensure output directory exists
            output_path = Path(request.output_path)
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            # Generate audio
            with open(output_path, "wb") as f:
                async for chunk in communicate.stream():
                    if chunk["type"] == "audio":
                        f.write(chunk["data"])
            
            return str(output_path)
            
        except Exception as e:
            raise TTSEngineError(f"Edge-TTS synthesis failed: {e}")
    
    async def get_available_voices(self) -> List[VoiceInfo]:
        """Get available voices from Edge-TTS."""
        await self._ensure_edge_tts()
        
        try:
            # Try to get voices from Edge-TTS API
            voices = await self._edge_tts.VoicesManager.create()
            voice_list = voices.voices
            
            # Convert to our VoiceInfo format
            available_voices = []
            for voice in voice_list:
                voice_info = VoiceInfo(
                    voice_id=voice["Name"],
                    name=voice["FriendlyName"],
                    language=voice["Locale"].split("-")[0],
                    gender=voice["Gender"],
                    locale=voice["Locale"],
                    sample_rate=24000,
                    description=voice.get("VoicePersonalities", [""])[0] if voice.get("VoicePersonalities") else None
                )
                available_voices.append(voice_info)
            
            return available_voices
            
        except Exception as e:
            # Fallback to builtin voice list
            print(f"Warning: Could not fetch voices from Edge-TTS API: {e}")
            print("Using builtin voice list...")
            return self._builtin_voices.copy()
    
    def _create_ssml(self, text: str, config: TTSConfig) -> str:
        """Create SSML (Speech Synthesis Markup Language) from text and config."""
        # Escape XML characters in text
        escaped_text = (text.replace("&", "&amp;")
                           .replace("<", "&lt;")
                           .replace(">", "&gt;")
                           .replace("\"", "&quot;")
                           .replace("'", "&apos;"))
        
        # Build prosody attributes
        prosody_attrs = []
        if config.rate and config.rate != "+0%":
            prosody_attrs.append(f'rate="{config.rate}"')
        if config.volume and config.volume != "+0%":
            prosody_attrs.append(f'volume="{config.volume}"')
        if config.pitch and config.pitch != "+0Hz":
            prosody_attrs.append(f'pitch="{config.pitch}"')
        
        # Create SSML
        if prosody_attrs:
            prosody_str = " ".join(prosody_attrs)
            ssml = f'<prosody {prosody_str}>{escaped_text}</prosody>'
        else:
            ssml = escaped_text
        
        return ssml
    
    def get_recommended_voice(self, language: str = "zh-CN") -> VoiceInfo:
        """Get recommended voice for language."""
        # Recommended voices for different languages
        recommendations = {
            "zh-CN": "zh-CN-XiaoxiaoNeural",  # 晓晓 - 活泼女声
            "zh": "zh-CN-XiaoxiaoNeural",
            "en-US": "en-US-AriaNeural",      # Aria - 自然女声
            "en": "en-US-AriaNeural",
        }
        
        voice_id = recommendations.get(language, "zh-CN-XiaoxiaoNeural")
        
        # Find voice in builtin list
        for voice in self._builtin_voices:
            if voice.voice_id == voice_id:
                return voice
        
        # Fallback to first available voice
        return self._builtin_voices[0]
    
    def get_voices_by_language(self, language: str) -> List[VoiceInfo]:
        """Get all voices for a specific language."""
        return [voice for voice in self._builtin_voices 
                if voice.language.startswith(language)]
    
    def get_male_voices(self, language: str = "zh-CN") -> List[VoiceInfo]:
        """Get male voices for language."""
        return [voice for voice in self._builtin_voices 
                if voice.language.startswith(language) and voice.gender == "Male"]
    
    def get_female_voices(self, language: str = "zh-CN") -> List[VoiceInfo]:
        """Get female voices for language."""
        return [voice for voice in self._builtin_voices 
                if voice.language.startswith(language) and voice.gender == "Female"]
    
    def create_config_preset(self, style: str = "default") -> TTSConfig:
        """Create predefined configuration presets."""
        presets = {
            "default": TTSConfig(
                voice_id="zh-CN-XiaoxiaoNeural",
                rate="+0%",
                volume="+0%",
                pitch="+0Hz"
            ),
            "fast": TTSConfig(
                voice_id="zh-CN-XiaoxiaoNeural",
                rate="+20%",
                volume="+0%",
                pitch="+0Hz"
            ),
            "slow": TTSConfig(
                voice_id="zh-CN-XiaoxiaoNeural",
                rate="-20%",
                volume="+0%",
                pitch="+0Hz"
            ),
            "deep_male": TTSConfig(
                voice_id="zh-CN-YunxiNeural",
                rate="-10%",
                volume="+0%",
                pitch="-20Hz"
            ),
            "bright_female": TTSConfig(
                voice_id="zh-CN-XiaoyiNeural",
                rate="+10%",
                volume="+10%",
                pitch="+20Hz"
            ),
            "professional": TTSConfig(
                voice_id="zh-CN-XiaoxuanNeural",
                rate="+0%",
                volume="+0%",
                pitch="+0Hz"
            ),
            "gentle": TTSConfig(
                voice_id="zh-CN-XiaochenNeural",
                rate="-10%",
                volume="-5%",
                pitch="-10Hz"
            )
        }
        
        return presets.get(style, presets["default"])


# Convenience function for quick TTS
async def quick_tts(text: str, 
                   voice_id: str = "zh-CN-XiaoxiaoNeural",
                   output_path: Optional[str] = None) -> str:
    """
    Quick TTS generation with minimal setup.
    
    Args:
        text: Text to synthesize
        voice_id: Voice to use
        output_path: Output file path (auto-generated if None)
        
    Returns:
        Path to generated audio file
    """
    engine = EdgeTTSEngine()
    config = TTSConfig(voice_id=voice_id)
    request = TTSRequest(text=text, config=config, output_path=output_path)
    return await engine.synthesize(request)